package com.beiding.my.bomapping;

import com.beiding.my.bemapping.BeTypeMapper;
import com.google.common.base.Joiner;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BoTypeMapper<T> {

    BoTypeMapper() {
    }

    private String id = Id.bot();

    //Bo 名称
    String name;

    //Bo 类型
    Class<T> type;

    BeTypeMapper beTypeMapper;

    /*
        name -> BoFieldMapper 内部指向 beTypeMapper 可将name赋给be实体
        teacher -> BoQuoteMapper 内部指向真实类型的 BoTypeMapper 将当前Bo内的 _quote_teacher 缺省新建

     */
    Map<String, BoAttributeMapper> boAttributeNameMapperMap = new HashMap<>();
    Map<String, BoAttributeMapper> boAttributeIdMapperMap = new HashMap<>();

    void addAttributeMapper(BoAttributeMapper mapper) {
        boAttributeNameMapperMap.put(mapper.getName(), mapper);
        boAttributeIdMapperMap.put(mapper.getId(), mapper);
    }

    public T newBoByAttributeName(Map<String, Object> values) {
        T bo = newBo();
        values.forEach((k, v) -> {
            //属性名称的分段
            String[] segments = k.split("\\.");
            assignmentByName(bo, segments, 0, v);
        });
        return bo;

    }

    //id也是分区段的
    public T newBoByAttributeId(Map<String, Object> values) {
        T bo = newBo();
        values.forEach((k, v) -> {

            //id使用下划线分隔
            String[] segments = k.split("_");
            assignmentById(bo, segments, 0, v);
        });
        return bo;
    }

    public String makeFieldIdByName(String name) {
        String[] nameSegments = name.split("\\.");
        List<String> idSegments = new ArrayList<>();
        makeIdByName(idSegments, nameSegments, 0);
        return Joiner.on("_").join(idSegments);
    }

    public void makeIdByName(List<String> idSegments, String[] nameSegments, int currentSegment) {
        BoAttributeMapper boAttributeMapper = boAttributeNameMapperMap.get(nameSegments[currentSegment]);
        if (boAttributeMapper == null) {
            throw new RuntimeException("不存在的Bo成员Id:" + type.getName() + ":" + nameSegments[currentSegment]);
        } else {
            boAttributeMapper.makeIdByName(idSegments, nameSegments, currentSegment);
        }
    }

    void assignmentById(Object bo, String[] segments, int currentSegment, Object v) {
        BoAttributeMapper boAttributeMapper = boAttributeIdMapperMap.get(segments[currentSegment]);
        if (boAttributeMapper == null) {
            throw new RuntimeException("不存在的Bo成员Id:" + type.getName() + ":" + segments[currentSegment]);
        } else {
            boAttributeMapper.handleById(bo, segments, currentSegment, v);
        }
    }

    void assignmentByName(Object bo, String[] segments, int currentSegment, Object v) {
        BoAttributeMapper boAttributeMapper = boAttributeNameMapperMap.get(segments[currentSegment]);
        if (boAttributeMapper == null) {
            throw new RuntimeException("不存在的Bo成员名称:" + type.getName() + ":" + segments[currentSegment]);
        } else {
            boAttributeMapper.handleByName(bo, segments, currentSegment, v);
        }
    }

    public T newBo() {
        try {
            return type.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    void fillExpressionDetails(String[] segments, int currentSegment, ExpressionDetails expressionDetails) {

        //填充所有字段类型的数据
        if (segments[currentSegment].equals("*")) {

            for (BoAttributeMapper boAttributeMapper : boAttributeNameMapperMap.values()) {
                if (boAttributeMapper instanceof BoFieldMapper) {
                    boAttributeMapper.fillExpressionDetails(beTypeMapper.getType(), segments, currentSegment, expressionDetails);
                }
            }

        } else {
            BoAttributeMapper boAttributeMapper = boAttributeNameMapperMap.get(segments[currentSegment]);
            if (boAttributeMapper == null) {
                throw new RuntimeException("不存在的Bo成员名称:" + type.getName() + ":" + segments[currentSegment]);
            } else {
                boAttributeMapper.fillExpressionDetails(beTypeMapper.getType(), segments, currentSegment, expressionDetails);
            }
        }
    }

    public ExpressionDetails getExpressionDetails(String name, String expression) {
        ExpressionDetails expressionDetails = new ExpressionDetails(name);
        String[] split = expression.split("\\.");
        fillExpressionDetails(split, 0, expressionDetails);
        return expressionDetails;
    }

    public String getBeTable() {
        return beTypeMapper.getTableName();
    }


}
